package com.xmlt.ui.builder;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;

import com.xmlt.core.template.TemplateManager;
import com.xmlt.ui.builder.generator.FileGenerationBuilder;

public class XMLTNature implements IProjectNature {
	private boolean inited = false;
	private Object monitor = new Object();

	/**
	 * ID of this project nature
	 */
	public static final String NATURE_ID = "com.xmlt.ui.builder.XMLTNature";

	private IProject project;
	private TemplateManager templateManager;

	public static void configureProject(IProject targetProject) throws CoreException {
		configureProject(targetProject, new HashMap());
	}

	public static void configureProject(IProject targetProject, Map arguments) throws CoreException {
		IProjectDescription desc = targetProject.getDescription();
		ICommand[] commands = desc.getBuildSpec();

		for (int i = 0; i < commands.length; ++i) {
			if (commands[i].getBuilderName().equals(XMLTBuilder.BUILDER_ID)) {
				return;
			}
		}

		ICommand[] newCommands = new ICommand[commands.length + 2];
		System.arraycopy(commands, 0, newCommands, 0, commands.length);
		
		ICommand command = desc.newCommand();
		command.setBuilderName(XMLTBuilder.BUILDER_ID);
		command.setArguments(arguments);
		newCommands[newCommands.length - 2] = command;
		
		ICommand generationbuilderCommand = desc.newCommand();
		generationbuilderCommand.setBuilderName(FileGenerationBuilder.BUILDER_ID);
		generationbuilderCommand.setArguments(arguments);
		newCommands[newCommands.length - 1] = generationbuilderCommand;
		
		desc.setBuildSpec(newCommands);
		targetProject.setDescription(desc, null);
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.resources.IProjectNature#configure()
	 */
	public void configure() throws CoreException {
		configureProject(project);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.resources.IProjectNature#deconfigure()
	 */
	public void deconfigure() throws CoreException {
		IProjectDescription description = getProject().getDescription();
		ICommand[] commands = description.getBuildSpec();
		for (int i = 0; i < commands.length; ++i) {
			if (commands[i].getBuilderName().equals(XMLTBuilder.BUILDER_ID)) {
				ICommand[] newCommands = new ICommand[commands.length - 1];
				System.arraycopy(commands, 0, newCommands, 0, i);
				System.arraycopy(commands, i + 1, newCommands, i,
						commands.length - i - 1);
				description.setBuildSpec(newCommands);
				project.setDescription(description, null);
			}
			if (commands[i].getBuilderName().equals(FileGenerationBuilder.BUILDER_ID)) {
				ICommand[] newCommands = new ICommand[commands.length - 1];
				System.arraycopy(commands, 0, newCommands, 0, i);
				System.arraycopy(commands, i + 1, newCommands, i,
						commands.length - i - 1);
				description.setBuildSpec(newCommands);
				project.setDescription(description, null);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.resources.IProjectNature#getProject()
	 */
	public IProject getProject() {
		return project;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core
	 * .resources.IProject)
	 */
	public void setProject(IProject p) {
		project = p;
		IResolverFactory resolverFactory = BuilderPlugin.getDefault().getResolverFactory();
		templateManager = new TemplateManager(resolverFactory.getResolver(project));
		try {
			ICommand[] buildCommands = project.getDescription().getBuildSpec();
			for (ICommand cmd: buildCommands) {
				if (cmd.getBuilderName().equals(XMLTBuilder.BUILDER_ID)) {
					Object argsObject = cmd.getArguments();
					if (argsObject instanceof Map) {
						Map argsMap = (Map) argsObject;
						
					}
				}
			}
		} catch (CoreException e) {
			e.printStackTrace();
		}
		
		initXMLTNature();
	}

	public TemplateManager getTemplateManager() {
		if (!inited) {
			initXMLTNature();
		}
		return templateManager;
	}
	
	public void waitForInit() {
		while (!inited) {
			synchronized (monitor) {
				try {
					monitor.wait(500);
				} catch (InterruptedException e) {
				}
			}
		}
	}
	
	private void initXMLTNature() {
		final XMLTBuilder builder = new XMLTBuilder(templateManager);
		Job launchJob = new Job("XMLT init") {

			@Override
			protected IStatus run(IProgressMonitor arg0) {
				synchronized (monitor) {
					try {
						project.accept(new IResourceVisitor() {
							
							@Override
							public boolean visit(IResource arg0) throws CoreException {
								builder.checkResource(arg0);
								return true;
							}
						});
					} catch (CoreException e) {
						//TODO: add error reporting
					}
					inited = true;
					monitor.notifyAll();
					return Status.OK_STATUS;
				}
			}
			
		};
		launchJob.setSystem(true);
		launchJob.schedule();
	}

}
